import datetime
import json
import sys
import time
import unittest
import requests

from commons import request_data
from test_suit.test_main import TestMain
from utils.func_utils import RequestUtils, DBUtils


class TestData(unittest.TestCase):
    def __init__(self, *args, **kwargs):
        super(TestData, self).__init__(*args, **kwargs)
        self.url = 'https://test-os-gateway.songguo7.com/api/iot/ste/control/cmd/batch/send'
        self.time_line_url = 'http://test-os-gateway.songguo7.com/api/iot-timeline/timeline/list'
        self.env = 'test'
        self.ecu = TestMain().e
        self.month = datetime.datetime.now().strftime('%Y%m')
        self.mobile = TestMain().agreement_dict['mobile']
        self.only_number = TestMain().agreement_dict['only_number']
        self.command_dict = dict()
        for item in request_data.COMMAND_DICT_LIST:
            self.command_dict[item['command_type']] = item['command_code']

    def get_req_params(self, channel_type, command_type, params_dict=None):
        # 组装请求参数, 数据库查询号码
        command_no = str(20231116) + self.ecu + str(int(time.time() * 1000))
        params = {
            "params": {
                "steStr": self.ecu,
                "channel_type": channel_type,
                "command_type": self.command_dict[command_type],
                "need_ack": True,
                "ste_sns": [self.ecu],
                "tenant_code": "1",
                "param": params_dict
            }
        }
        return params, command_no

    def get_req_data(self, channel_type, command_type, data_dict=None):
        # 组装请求数据, 数据库查询号码
        command_no = str(20231116) + self.ecu + str(int(time.time() * 1000))
        params = {
            "params": {
                "steStr": self.ecu,
                "channel_type": channel_type,
                "command_type": self.command_dict[command_type],
                "need_ack": True,
                "ste_sns": [self.ecu],
                "tenant_code": "1",
                "data": data_dict
            }
        }
        return params, command_no

    def assert_mysql_send_net(self):
        sql = '''
            SELECT * FROM tnotice.iot_sms_send_{}01 order by create_time desc limit 1
            '''.format(self.month)
        print("数据库查询语句：", sql)
        data = DBUtils().conn_db(sql)
        content = data[0][6]
        status = data[0][7]
        return content, status

    def assert_mysql_send_api(self):
        sql = ('''
                SELECT * FROM tnotice.iot_sms_send_{}01 where mobile={} order by create_time desc limit 1
                '''.format(self.month, self.mobile))
        print("数据库查询语句：", sql)
        data = DBUtils().conn_db(sql)
        content = data[0][6]
        msg_set_argument = content.split(',')[2]
        message_id = content.split(',')[5].strip('$')
        msgid = data[0][3]
        return msg_set_argument, message_id, msgid

    def assert_mysql_report(self):
        sql = ('''
                SELECT * FROM tnotice.iot_sms_report_{}01 where mobile={} order by create_time desc limit 1
                '''.format(self.month, self.mobile))
        print("数据库查询语句：", sql)
        data = DBUtils().conn_db(sql)
        msgid = data[0][2]
        return msgid

    def assert_sms_reply(self):
        sql = ('''
                SELECT * FROM tnotice.iot_sms_replay_{}01 where mobile={} order by create_time desc limit 1
                '''.format(self.month, self.mobile))
        print("数据库查询语句：", sql)
        data = DBUtils().conn_db(sql)
        content = data[0][4]
        res_code = content.split(',')[2]
        argument_res = content.split(',')[3]
        message_id = content.split(',')[4]
        return res_code, argument_res, message_id

    def get_logs_query(self, time_line_types, cmd=None, number=None, start_time=None):
        # 日志查询
        if cmd is None:
            cmd = ""
        if start_time is not None:
            start_time = TestMain().start_time_2
        else:
            start_time = TestMain().start_time
        query = {
            "params": {
                "page_size": "1000",
                "bike_sn": "",
                "ecu_sn": self.ecu,
                "cmd": cmd,
                "cmd_code": "",
                "timeline_start_time": start_time,
                "timeline_end_time": TestMain().end_time,
                "time_linetypes": [
                    time_line_types
                ],
                "scroll_id": "",
                "gsm_signal_strength": "",
                "standby_battery_capacity": "",
                "parse_able": True
            }
        }
        # print("日志查询参数：", query)
        datas = json.dumps(query)
        response = RequestUtils().all_request(method='POST', url=self.time_line_url, data=datas,
                                              headers=DBUtils().get_headers(self.env), timeout=None)
        print("日志查询响应：")
        if 'error' in response.json().keys():
            response = RequestUtils().all_request(method='POST', url=self.time_line_url, data=datas,
                                                  headers=DBUtils().update_token(self.env))
            data = response.json()['data']
            time_line_record_list = data['time_line_record_entities']
            if number is None:
                return time_line_record_list[0]
            else:
                return time_line_record_list
        else:
            data = response.json()['data']
            time_line_record_list = data['time_line_record_entities']
            if number is None:
                try:
                    return time_line_record_list[0]
                except:
                    print("日志查询失败！")
            else:
                return time_line_record_list

    def request_and_assert_params(self, val0, val1, val2=None):
        '''
        命令下发、iot查找关联下发命令、及响应状态
        如果为短信命令，则需要在数据库中校验指令状态
        '''
        par, command_no = self.get_req_params(val0, val1, val2)
        print("请求参数：", par)
        response = RequestUtils().all_request(method='POST', url=self.url, json=par,
                                              headers=DBUtils().get_headers(self.env))
        time.sleep(10)
        response_json = response.json()
        print("响应结果：", response_json)
        self.assertEqual(0, response_json['code'], "请求失败！")
        if response_json['data'] is None:
            print("指令下发失败！\n退出测试！")
            sys.exit(0)
        command_no = response_json['data']['send_success_commands'][0]['command_no']
        print("指令编号：", command_no)
        if val0 == 'SMS':
            time.sleep(20)
            content, status = self.assert_mysql_send_net()
            self.assertIn(command_no, content, "数据库未找到指令编号！")
            self.assertIn(self.command_dict[val1], content, "数据库未找到指令！")
            self.assertEqual('0', status, "设备指令失败！")
        elif val0 == 'NET':
            if (val1 == 'HELMENT_BORROW' or val1 == 'HELMENT_RETURN' or
                    val1 == "SMART_HELMET_UNLOCK" or val1 == "SMART_HELMET_LOCK"):
                self.assertIn(command_no, json.dumps(self.get_logs_query(10)), '没有在iot平台查到指令下发报文')
                time.sleep(20)
                act = json.dumps(self.get_logs_query(20))
                self.assertIn(command_no, act, '没有在iot平台查到指令结果报文')
                self.assertIn(r'"status": 204', act, '没有在iot平台查到指令状态')
                return act
            else:
                self.assertIn(command_no, json.dumps(self.get_logs_query(10)), '没有在iot平台查到指令下发报文')
                time.sleep(20)
                act = json.dumps(self.get_logs_query(20))
                self.assertIn(command_no, act, '没有在iot平台查到指令结果报文')
                self.assertIn(r'"status": 200', act, 'iot平台响应结果报文code不正确')
                return act

    def request_and_assert_data(self, val0, val1, val2=None):
        '''
        上传数据、iot查找关联下发命令、及响应状态
        '''
        if val2 is None:
            val2 = {}
        par, command_no = self.get_req_data(val0, val1, val2)
        response = RequestUtils().all_request(method='POST', url=self.url, json=par)
        response_json = response.json()
        self.assertEqual(0, response_json['code'], "下发控制指令响应结果code不成功！")
        time.sleep(5)
        if val0 == 'SMS':
            time.sleep(20)
            content, status = self.assert_mysql_send_net()
            self.assertIn(command_no, content, "数据库未找到指令编号！")
            self.assertIn(self.command_dict[val1], content, "数据库未找到指令！")
            self.assertEqual('0', status, "设备指令失败！")
        else:
            if (val1 == "HELMET_BORROW" or val1 == "HELMET_RETURN" or val1 == "SMART_HELMET_UNLOCK" or
                    val1 == "SMART_HELMET_LOCK" or val1 == "CLOSE_HELMET_LOCK"):
                self.assertIn(command_no, json.dumps(self.get_logs_query(10)), '没有在iot平台查到指令下发报文')
                time.sleep(20)
                act = json.dumps(self.get_logs_query(10))
                self.assertIn(command_no, act, '没有在iot平台查到指令结果报文')
                self.assertIn(r'"status": 204', act, '没有在iot平台查到指令状态')
                return act
            else:
                self.assertIn(command_no, json.dumps(self.get_logs_query(10)), '没有在iot平台查到指令下发报文')
                time.sleep(20)
                act = json.dumps(self.get_logs_query(10))
                self.assertIn(command_no, act, '没有在iot平台查到指令结果报文')
                self.assertIn(r'"status": 200', act, 'iot平台响应结果报文code不正确')
                return act

    def send_sms_command(self, cmd, reply, is_over_date, argument=None):
        url = 'http://test-titan.songguo7.com/iot-sms/send'
        command_no = str(202010130000000) + str(int(time.time() * 1000))
        now_time = int(time.time())
        if is_over_date == 'Y':
            now_time = now_time - 150
        elif is_over_date == 'N':
            now_time = now_time + 150
        query = {}
        if argument is None:
            query = {
                "card_no": self.mobile,
                "from": "iot",
                "content": "${},{},,{},{},{}$".format(self.only_number, cmd, now_time, reply, command_no)
            }
        elif argument is not None:
            query = {
                "card_no": self.mobile,
                "from": "iot",
                "content": "${},{},{},{},{},{}$".format(self.only_number, cmd, argument, now_time, reply, command_no)
            }
        response = RequestUtils().all_request(method='POST', url=url, json=query)
        response_json = response.json()
        self.assertEqual(0, response_json['code'], "下发控制指令响应结果code不成功！")
        time.sleep(5)
        msg_set_argument, message_id, msgid = self.assert_mysql_send_api()
        self.assertIn(command_no, message_id, "下发的message_id与send数据库不符！")
        time.sleep(15)
        self.assertEqual(msgid, self.assert_mysql_report(), "下发的msgid和report数据库不符！")
        time.sleep(15)
        if reply == 'Y':
            res_code, argument_res, message_id_replay = self.assert_sms_reply()
            self.assertEqual(res_code, '0', "设备执行指令回复失败！")
            self.assertIn(command_no, message_id_replay, "下发指令的message_id与reply数据库不符！")
            if cmd == '331' and argument.split(',')[0] in ("VIBL;FREQ;PULSE;DOMAIN;BLEKG;SLEEPT;MAXECUSPEED;"
                                                           "SWITCHMODESOC;DFTOUTPOFFILTERT;DFTLOCKVOICEPLAYT;ALARMFREQ;"
                                                           "DIAMETER;ALNICONUM;DFTTIMEOUT;BTNAME;OSDSWITCH;OSDSPEED;"
                                                           "OSDTIMEINTERVAL;OSDTIMEMAX;OSDRING;LOCKINGTIME;"
                                                           "GLOBALVOLUME;VIBLVOICESW;DV-301;DV-304;HELMETAUDIO-1;"
                                                           "HELMETAUDIO-2;HELMETAUDIO-3;HELMETAUDIO-4;HELMETAUDIO-5;"
                                                           "HELMETAUDIO-6;HELMETAUDIO-7;HELMETAUDIO-8;HELMETAUDIO-9;"
                                                           "HELMETAUDIO-10;HELMETAUDIO-11;HELMETAUDIO-12;"
                                                           "HELMETAUDIO-13;HELMETAUDIO-14;HELMETAUDIO-15;"
                                                           "HELMETAUDIO-16;HELMETAUDIO-17;PLAYAUDIOCNT;"
                                                           "HE-TIMEOUT;HELMETAUDIO-18;HELMETAUDIO-19;HELMETAUDIO-20;"
                                                           "HELMETAUDIO-21;"):
                self.assertNotIn('FAIL', argument_res)
            elif cmd == '331' and argument.split('=')[0] in ("SOFTVERSION;HARDVERSION;VOICEVERSION;VOICELEFTSPACE;"
                                                             "CTRLVERSION;BMSVERSION;GSM;VBAT;VIN;DEVICESN;DEVICESTATUS;"
                                                             "BATVER;BATMANUFACTURE;BATSN"):
                self.assertNotIn('FAIL', argument_res)
            elif cmd == '330':
                self.assertNotIn('FAIL', argument_res)
            else:
                pass
        else:
            pass

